Previous: Type Keywords, Up: Customization Types [Contents][Index]
In the previous sections we have described how to construct
elaborate type specifications for defcustom. In some
cases you may want to give such a type specification a name. The
obvious case is when you are using the same type for many user
options: rather than repeat the specification for each option,
you can give the type specification a name, and use that name
each defcustom. The other case is when a user
option’s value is a recursive data structure. To make it
possible for a datatype to refer to itself, it needs to have a
name.
Since custom types are implemented as widgets, the way to define a new customize type is to define a new widget. We are not going to describe the widget interface here in details, see Introduction in The Emacs Widget Library, for that. Instead we are going to demonstrate the minimal functionality needed for defining new customize types by a simple example.
(define-widget 'binary-tree-of-string 'lazy
"A binary tree made of cons-cells and strings."
:offset 4
:tag "Node"
:type '(choice (string :tag "Leaf" :value "")
(cons :tag "Interior"
:value ("" . "")
binary-tree-of-string
binary-tree-of-string)))
(defcustom foo-bar ""
"Sample variable holding a binary tree of strings."
:type 'binary-tree-of-string)
The function to define a new widget is called
define-widget. The first argument is the symbol we
want to make a new widget type. The second argument is a symbol
representing an existing widget, the new widget is going to be
defined in terms of difference from the existing widget. For the
purpose of defining new customization types, the
lazy widget is perfect, because it accepts a
:type keyword argument with the same syntax as the
keyword argument to defcustom with the same name.
The third argument is a documentation string for the new widget.
You will be able to see that string with the M-x
widget-browse RET binary-tree-of-string
RET command.
After these mandatory arguments follow the keyword arguments.
The most important is :type, which describes the
data type we want to match with this widget. Here a
binary-tree-of-string is described as being either a
string, or a cons-cell whose car and cdr are themselves both
binary-tree-of-string. Note the reference to the
widget type we are currently in the process of defining. The
:tag attribute is a string to name the widget in the
user interface, and the :offset argument is there to
ensure that child nodes are indented four spaces relative to the
parent node, making the tree structure apparent in the
customization buffer.
The defcustom shows how the new widget can be
used as an ordinary customization type.
The reason for the name lazy is that the other
composite widgets convert their inferior widgets to internal form
when the widget is instantiated in a buffer. This conversion is
recursive, so the inferior widgets will convert their
inferior widgets. If the data structure is itself recursive, this
conversion is an infinite recursion. The lazy widget
prevents the recursion: it convert its :type
argument only when needed.
Previous: Type Keywords, Up: Customization Types [Contents][Index]